package com.ys.service.base.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.ys.entity.business.TbBaseInfo;
import com.ys.entity.finance.TcwFinancialTransactionTypeItem;
import com.ys.enume.base.TransactionTypeEnum;
import com.ys.enume.finance.TcwFinancialTransactionFlowEnum;
import com.ys.service.finance.TcwFinancialTransactionFlowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.config.MenuId;
import com.ys.dto.AddDto;
import com.ys.entity.base.TbMedicarePay;
import com.ys.entity.base.TbMedicarePayItem;
import com.ys.entity.finance.TcwAccountDetailedForCompany;
import com.ys.entity.finance.TcwPartnerBankInfo;
import com.ys.entity.flow.YspModel;
import com.ys.entity.sys.TsUserChange;
import com.ys.entity.sys.YsCol;
import com.ys.entity.sys.YsMenu;
import com.ys.enume.flow.FlowEnum;
import com.ys.mapper.base.TbMedicarePayItemMapper;
import com.ys.mapper.base.TbMedicarePayMapper;
import com.ys.mapper.business.DiySqlMapper;
import com.ys.service.base.TbMedicarePayService;
import com.ys.service.flow.YspTaskService;
import com.ys.util.CheckUtil;
import com.ys.util.RandomUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;

//医保付款单
@Service("tbMedicarePayService")
public class TbMedicarePayServiceImpl implements TbMedicarePayService {

    @Autowired
    private TbMedicarePayMapper tbMedicarePayMapper;

    @Autowired
    private TbMedicarePayItemMapper tbMedicarePayItemMapper;

    @Autowired
    private CheckUtil checkUtil;

    @Autowired
    private YspTaskService yspTaskService;

    @Autowired
    private DiySqlMapper diySqlMapper;

    @Autowired
    private TcwFinancialTransactionFlowService tcwFinancialTransactionFlowService;




    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R add(Map<String, Object> params, String subData) throws Exception {
        //验证
        String msg = yzMsg(params);
        if (msg != null){
            return R.error(msg);
        }
        TbMedicarePay tbMedicarePay = JSON.parseObject(JSON.toJSONString(params), TbMedicarePay.class);
        if (new TbMedicarePay().setBid(tbMedicarePay.getBid()).count() != 0){
            return R.error("该单号已存在，核实后再操作!");
        }

        // 验证是否有详情数据
        JSONArray detailJA = JSON.parseArray(subData);
        if (detailJA == null || detailJA.size() == 0) {
            return R.error("详情数据不能为空");
        }
        String loginUserId = ShiroUtils.getUserId();
        TsUserChange tsUserChange = new TsUserChange().setUserId(loginUserId).setStatus(1).queryFirst();

        tbMedicarePay.setStatus(0);
        tbMedicarePay.setCreateChangeId(String.valueOf(tsUserChange.getId()));
        tbMedicarePay.setEffectStock(FlowEnum.EffectStock.NOT_EFFECT.value);
        tbMedicarePayMapper.insert(tbMedicarePay);
        for (int i = 0; i < detailJA.size(); i++) {
            JSONObject detailJO = detailJA.getJSONObject(i);
            TbMedicarePayItem tbMedicarePayItem = JSON.parseObject(JSON.toJSONString(detailJO), TbMedicarePayItem.class);
            tbMedicarePayItem.setMedicarePayBid(tbMedicarePay.getBid());
            if(detailJO.get("vgsbm") == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error("运营公司不能为空,不允许保存!");
            }
            if (detailJO.get("vbzXq") != null){
                tbMedicarePayItem.setVbz(detailJO.get("vbzXq").toString());
            }
            if (new TbMedicarePayItem().setUserMonthPerformanceId(tbMedicarePayItem.getUserMonthPerformanceId()).count() != 0){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error("数据已新增,不允许保存!");
            }
            tbMedicarePayItemMapper.insert(tbMedicarePayItem);
        }


        YsMenu ysMenu = new YsMenu().setId(MenuId.TB_MedicarePay).queryFirst();
        if (ysMenu.getFlowModelId().longValue() != 0L) {
            YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
            String codeModel = yspModel.getCode();
            String createUserId = ShiroUtils.getUserId();
            yspTaskService.init(codeModel, tbMedicarePay.getBid(), createUserId);
            yspTaskService.setOtherParams(tbMedicarePay.getBid(),tbMedicarePay.getVbz(),params.get("orgName"));
        }

        return R.ok(AddDto.gotoEdit("/web/base/tbMedicarePay/toEdit?bid=" + tbMedicarePay.getBid()));
    }

    /**
     * 修改医保付款单
     * @param params
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R edit(Map<String, Object> params,String subData) throws Exception {

        //验证
        String msg = yzMsg(params);
        if (msg != null){
            return R.error(msg);
        }
        TbMedicarePay tbMedicarePay = JSON.parseObject(JSON.toJSONString(params), TbMedicarePay.class);
        if (new TbMedicarePay().setBid(tbMedicarePay.getBid()).where("A.id != " + tbMedicarePay.getId()).count() != 0){
            return R.error("该单号已存在，核实后再操作!");
        }

        // 验证是否有详情数据
        JSONArray detailJA = JSON.parseArray(subData);
        if (detailJA == null || detailJA.size() == 0) {
            return R.error("详情数据不能为空");
        }

        //判断是否实在制单中
        Integer flowState = yspTaskService.flowState(tbMedicarePay.getBid());

        if (flowState != 0){
            return R.error("医保付款单不是制单中,不允许保存!");
        }
        tbMedicarePayMapper.update(tbMedicarePay);

        //批量删除
        diySqlMapper.deleteTbMedicarePayItemBid(tbMedicarePay.getBid());

        for (int i = 0; i < detailJA.size(); i++) {
            JSONObject detailJO = detailJA.getJSONObject(i);
            TbMedicarePayItem tbMedicarePayItem = JSON.parseObject(JSON.toJSONString(detailJO), TbMedicarePayItem.class);
            tbMedicarePayItem.setMedicarePayBid(tbMedicarePay.getBid());
            if (detailJO.get("vbzXq") != null){
                tbMedicarePayItem.setVbz(detailJO.get("vbzXq").toString());
            }
            if(detailJO.get("vgsbm") == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error("运营公司不能为空,不允许保存!");
            }
            if (new TbMedicarePayItem().setUserMonthPerformanceId(tbMedicarePayItem.getUserMonthPerformanceId()).where("A.id != " + tbMedicarePayItem.getId()).count() != 0){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error("数据已新增,不允许保存!");
            }
            tbMedicarePayItemMapper.insert(tbMedicarePayItem);
        }
        yspTaskService.setOtherParams(tbMedicarePay.getBid(),tbMedicarePay.getVbz(),params.get("orgName"));
        return R.ok(AddDto.gotoEdit("/web/base/tbMedicarePay/toEdit?bid=" + tbMedicarePay.getBid()));
    }


    /**
     * 删除
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R delete(Long id) {
        try {
            TbMedicarePay tbMedicarePay = new TbMedicarePay().setId(id).queryFirst();
            if (tbMedicarePay == null){
                return R.error("医保付款单不存在!");
            }

            //判断是否实在制单中
            Integer flowState = yspTaskService.flowState(tbMedicarePay.getBid());

            if (flowState != 0){
                return R.error("医保付款单不是制单中,不允许保存!");
            }
            tbMedicarePayMapper.deleteTrue(id);

            //批量删除
            diySqlMapper.deleteTbMedicarePayItemBid(tbMedicarePay.getBid());
            //删除任务
            yspTaskService.flowDelete(tbMedicarePay.getBid(),tbMedicarePay.getCreateChangeId());
        } catch (Exception e) {
            return R.error("删除失败!");
        }
        return R.ok("删除成功!");
    }

    /**
     * 流转
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R flowPass(Long id, String loginUserId) throws Exception {
        TbMedicarePay entity = new TbMedicarePay().setId(id).queryFirst();
        String bid = entity.getBid();
        try {
            Flow f = yspTaskService.flowPass(bid, loginUserId);
            if (f.getCode() == Flow.Code.FAILED.value) {
                return R.error(f.getMsg());
            } else {

                if (f.getState() == Flow.State.FINISH.value) {
                    R r = flowFinish(entity);
                    if (r.getCode() == 1) {
                        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                        return R.error(r.getMsg());
                    }
                }
                return R.ok();
            }
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.error("服务器正在开小差，请联系客服");
        }
    }


    /**
     * 退回
     * @param id
     * @param reason
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R flowRefuse(Long id, String reason, String loginUserId) throws Exception {
        try {
            TbMedicarePay entity = new TbMedicarePay().setId(id).queryFirst();
            String bid = entity.getBid();
            R r = yspTaskService.flowRefuse(bid, reason, loginUserId);
            if (r.getCode() == 1){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error(r.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.error("服务器正在开小差，请联系客服");
        }
        return R.ok();
    }

    /**
     * 驳回
     * @param id
     * @param reason
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R flowInit(Long id, String reason, String loginUserId) throws Exception {
        try {
            TbMedicarePay entity = new TbMedicarePay().setId(id).queryFirst();
            String bid = entity.getBid();
            R r = yspTaskService.flowInit(bid, reason, loginUserId);
            if (r.getCode() == 1){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error(r.getMsg());
            }
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.error("服务器正在开小差，请联系客服");
        }
        return R.ok();
    }

    private String yzMsg(Map<String, Object> infoMap){
        //验证导入字段
        String backMsg = "";
        //获取pc字段数据
        List<YsCol> listField = new YsCol()
                .where("A.MenuId = "+ MenuId.TB_MedicarePay)
                .setOrderby("A.SortNo ASC")
                .queryList();
        //验证必填字段的非空；其他字段的长度限制、类型
        try {
            backMsg = checkUtil.checkTableColLengthAndDataType(
                    "TB_MedicarePay",
                    listField,
                    infoMap,
                    ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1
            );
            if(backMsg!=null && !"".equals(backMsg)){//若有误，则跳过这条信息
                return backMsg;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public R flowFinish(TbMedicarePay entity) throws Exception {
        Date date = new Date();
        entity.setEffectStock(FlowEnum.EffectStock.EFFECTED.value);
        tbMedicarePayMapper.update(entity);

        //合作商信息
        TcwPartnerBankInfo tcwPartnerBankInfo = new TcwPartnerBankInfo().setId(entity.getPartnerBankId()).queryFirst();
        if (tcwPartnerBankInfo == null){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.error("收款账号不存在,核实后再操作!");
        }

        //查询子件信息
        List<Map<String,Object>> sonlist = new TbMedicarePayItem()
                .setMedicarePayBid(entity.getBid())
                .addLeftJoin("TB_UserMonthPerformance R ON R.id = A.UserMonthPerformanceId")//月度绩效
                .addField("A.healthCompany AS healthCompany")//医疗保险（单位）
                .addField("A.healthPersonal AS healthPersonal")//医疗保险（个人）
                .addField("A.birthCompany AS birthCompany")//生育保险（单位）
                .addLeftJoin("TS_UserInfo U ON U.UserId = R.UserId")//用户信息表
                .addField("U.UserId AS userId")//工号
                .addField(" U.UserName AS userName")//姓名
                .addLeftJoin("TS_OrganizationInfo O ON O.OrgId = R.OrgId")//组织机构表
                .addField("O.OrgName AS orgName")//所属公司
                .addLeftJoin("TS_OrganizationAccount oa ON oa.OrgId = U.DeptId")//部门绑定账号
                .addLeftJoin("THR_OperateCompanyApply THRO ON  THRO.Vgsbm = oa.Vgsbm")
                .addField("THRO.Vgsbm AS vgsbm,THRO.vgsjc AS vgsjc")//运营公司

                .addLeftJoin("TS_UserBankInfo ubi ON  ubi.UserId = R.UserId")
                .addField("ubi.vyhzh AS ygvyhzh,ubi.vkhh AS ygvkhh,ubi.vyhzhmc AS ygvyhzhmc")//收款信息
                .queryMap();

        //获取业务交易类型信息
        String transactionTypeStrByUser = TransactionTypeEnum.FinanceType.TB_MedicarePay_User.name;;
        TbBaseInfo transactionTypeItemByUser = tcwFinancialTransactionFlowService.getTransactionType(transactionTypeStrByUser);

        //获取业务交易类型信息
        String transactionTypeStrByCompany = TransactionTypeEnum.FinanceType.TB_MedicarePay_Company.name;;
        TbBaseInfo transactionTypeItemByCompany = tcwFinancialTransactionFlowService.getTransactionType(transactionTypeStrByCompany);

        for (Map<String,Object> son : sonlist){
            if (son.get("vgsbm") == null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return R.error("运营公司不存在,核实后再操作!");
            }
            //运营公司交易流水
            TcwAccountDetailedForCompany tcwAccountDetailedForCompany = new TcwAccountDetailedForCompany();
            tcwAccountDetailedForCompany.setGuid(RandomUtil.getGUID());
            tcwAccountDetailedForCompany.setVgsbm(son.get("vgsbm").toString());
            tcwAccountDetailedForCompany.setVgsjc(son.get("vgsjc").toString());
            tcwAccountDetailedForCompany.setVgsbmp(tcwPartnerBankInfo.getVid());
            tcwAccountDetailedForCompany.setVgsjcp(tcwPartnerBankInfo.getVyhzhmc());
            tcwAccountDetailedForCompany.setVjylx(transactionTypeStrByUser);
            tcwAccountDetailedForCompany.setFje(new BigDecimal(son.get("healthPersonal").toString()).negate());
            tcwAccountDetailedForCompany.setDjysj(entity.getCreateTime());
            tcwAccountDetailedForCompany.setDshsj(date);
            tcwAccountDetailedForCompany.setWriteTime(date);
            tcwAccountDetailedForCompany.setVbz("医保付款单:"+entity.getBid() + "，工号/姓名:" + son.get("userId").toString()+"/"+ son.get("userName").toString()
                    +",个人医保");
            diySqlMapper.insertTcwAccountDetailedForCompany(tcwAccountDetailedForCompany);

            BigDecimal fje = (new BigDecimal(son.get("healthCompany").toString()).add(new BigDecimal(son.get("birthCompany").toString()))).negate();
            TcwAccountDetailedForCompany tcwAccountDetailedForCompanyNew = new TcwAccountDetailedForCompany();
            tcwAccountDetailedForCompanyNew.setGuid(RandomUtil.getGUID());
            tcwAccountDetailedForCompanyNew.setVgsbm(son.get("vgsbm").toString());
            tcwAccountDetailedForCompanyNew.setVgsjc(son.get("vgsjc").toString());
            tcwAccountDetailedForCompanyNew.setVgsbmp(tcwPartnerBankInfo.getVid());
            tcwAccountDetailedForCompanyNew.setVgsjcp(tcwPartnerBankInfo.getVyhzhmc());
            tcwAccountDetailedForCompanyNew.setVjylx(transactionTypeStrByCompany);
            tcwAccountDetailedForCompanyNew.setFje(fje);
            tcwAccountDetailedForCompanyNew.setDjysj(entity.getCreateTime());
            tcwAccountDetailedForCompanyNew.setDshsj(date);
            tcwAccountDetailedForCompanyNew.setWriteTime(date);
            tcwAccountDetailedForCompanyNew.setVbz("医保付款单:"+entity.getBid() + "，工号/姓名:" + son.get("userId").toString()+"/"+ son.get("userName").toString()
                    +",单位医保 " );
            diySqlMapper.insertTcwAccountDetailedForCompany(tcwAccountDetailedForCompanyNew);

            //财务交易流水
            //个人
            if(transactionTypeItemByUser!=null && transactionTypeItemByUser.getId()!=null){
                R res = tcwFinancialTransactionFlowService.add(false, entity.getCompanyBankId(), transactionTypeItemByUser.getBid(),
                        son.get("ygvyhzhmc").toString(), son.get("ygvkhh").toString(), son.get("ygvyhzh").toString(), new BigDecimal(son.get("healthPersonal").toString()).negate(),
                        entity.getCreateTime(),date,new Date(),"医保付款单："+entity.getBid()+"，，工号/姓名:" + son.get("userId").toString()+"/"+ son.get("userName").toString()+",个人医保",
                        TcwFinancialTransactionFlowEnum.FromType.TB_MedicarePayItem.value,Long.parseLong(son.get("id").toString()));
                if(res.getCode().equals( R.Code.FAILED.value)){
                   return R.error(res.getMsg());
                }
            }


            //单位
            if(transactionTypeItemByCompany!=null && transactionTypeItemByCompany.getId()!=null){
                R res = tcwFinancialTransactionFlowService.add(true, entity.getCompanyBankId(), transactionTypeItemByCompany.getBid(),
                        son.get("ygvyhzhmc").toString(), son.get("ygvkhh").toString(), son.get("ygvyhzh").toString(), fje,
                        entity.getCreateTime(),date,new Date(),"医保付款单："+entity.getBid()+"，，工号/姓名:" + son.get("userId").toString()+"/"+ son.get("userName").toString()+",单位医保",
                        TcwFinancialTransactionFlowEnum.FromType.TB_MedicarePayItem.value,Long.parseLong(son.get("id").toString()));
                if(res.getCode().equals( R.Code.FAILED.value)){
                    throw new IllegalArgumentException(res.getMsg());
                }
            }

        }
        return R.ok();
    }


    //获取列表数据
    @Override
    @Transactional
    public Map<String,Object> getExtraParam( String bid) throws Exception{
        Map<String,Object> entity = new TbMedicarePay().setBid(bid)
                .addLeftJoin("YS_ProcInst Ysp ON Ysp.bid = A.bid")//流程表
                .addField("Ysp.updateTime AS updateTime1")
                .addLeftJoin("TB_CompanyBankInfo cbi ON cbi.id = A.CompanyBankId")//公司银行信息
                .addField("cbi.Vyhzh AS vyhzh,cbi.Vkhh AS vkhh,cbi.Vyhzhmc AS vyhzhmc")
                .addLeftJoin("TCW_PartnerBankInfo pbi ON pbi.id = A.PartnerBankId")//收款人银行
                .addField("pbi.Vyhzh AS hzvyhzh,pbi.Vkhh AS hzvkhh,pbi.vyhzhmc AS hzvyhzhmc")
                .queryFirstMap();
        BigDecimal healthCompany = BigDecimal.ZERO;
        BigDecimal healthPersonal = BigDecimal.ZERO;
        String orgName = "";
        List<Map<String, Object>> sonlist = getItemList(  bid);

        for (Map<String, Object> son : sonlist){
            healthCompany = healthCompany.add(new BigDecimal(son.get("healthCompany").toString())).add(new BigDecimal(son.get("birthCompany").toString()));
            healthPersonal = healthPersonal.add(new BigDecimal(son.get("healthPersonal").toString()));
            orgName = son.get("orgName").toString();
        }
        entity.put("healthCompany",healthCompany);
        entity.put("healthPersonal",healthPersonal);
        entity.put("healthTol",healthCompany.add(healthPersonal));
        entity.put("orgName",orgName);
        return entity;
    }
    //获取子列表数据
    @Override
    @Transactional
    public List<Map<String, Object>> getItemList( String bid) throws Exception{
        List<Map<String, Object>> sonlist = new TbMedicarePayItem()
                .setMedicarePayBid(bid)
                .addLeftJoin("TB_UserMonthPerformance R ON R.id = A.UserMonthPerformanceId")//月度绩效
                .addField("R.pointMonth AS pointMonth")//发薪月份
                .addField("R.pointMonth AS payDate")//缴费年月
                //				.addField("SUBSTRING(CONVERT(varchar, DATEADD(MONTH,1,R.pointMonth + '-01'), 23),0,8) AS payDate")//缴费年月
                .addField("A.healthCompany AS healthCompany")//医疗保险（单位）
                .addField("A.healthPersonal AS healthPersonal")//医疗保险（个人）
                .addField("A.birthCompany AS birthCompany")//生育保险（单位）


                .addLeftJoin("TS_UserInfo U ON U.UserId = R.UserId")//用户信息表
                .addField("(U.UserId + '/' + U.UserName) AS userName")//工号/姓名
                .addLeftJoin("TS_OrganizationInfo oi ON oi.OrgId = U.DeptId")//组织机构表
                .addField("oi.OrgName AS deptName")//部门

                .addLeftJoin("THR_UserArchives UAS ON UAS.UserId = R.UserId")//用户档案表
                .addField("UAS.UserState AS userState")//员工状态

                .addLeftJoin("TS_OrganizationInfo O ON O.OrgId = R.OrgId")//组织机构表
                .addField("O.OrgName AS orgName")//所属公司
                .addLeftJoin("TS_OrganizationAccount oa ON oa.OrgId = U.DeptId AND oa.Status = 1")//部门绑定账号
                .addLeftJoin("THR_OperateCompanyApply THRO ON  THRO.Vgsbm = oa.Vgsbm")
                .addField("oa.Vgsbm AS vgsbm,THRO.vgsjc AS vgsjc")//运营公司

                .addLeftJoin("TS_UserBankInfo ubi ON  ubi.UserId = U.UserId")
                .addField("ubi.vyhzh AS ygvyhzh,ubi.vkhh AS ygvkhh,ubi.vyhzhmc AS ygvyhzhmc")//收款信息

                .addField("R.Rank AS rank")//岗位职级
                .addField("R.Type AS type")//岗位工种(0总经理 1副总经理 2责任月薪型员工 3绩效提奖型员工 4研发人员)
                .addField("R.Category AS category")//岗位类别
                .addField("A.id AS userMonthPerformanceId")//id
                .addField("A.vbz AS vbzXq")//详情备注
                .queryMap();
        return sonlist;
    }

}
